# -*- coding: utf-8 -*-
'''
@author: wangwl
@file: jar
@time: 2021/09/15 09:45
@desc:
'''
import os
import threading
import time
import traceback
from components.resource_management.system_other_privilege.dao import sys_other_privilege_dict
from general.deploy.dao import deploy_event_in
from general.deploy.deploy_conf_create import DeployConfCreate
from utils.git_utils import GitClass
from utils.maven_utils import MvnClass
from utils.mysql_utils import sql_decrypt
from utils.ssh_utils import SCPMet
from utils.views import ReturnClass
from django.conf import settings
check_period = 5
check_count = 24

class DeployJar():
    def __init__(self, soft_info, conf_list):
        self.soft_info = soft_info
        self.conf_list = conf_list
        self.docker_compose_data = ''
        self.mvn_obj = MvnClass()

    def set_ssh(self):
        self.ssh = SCPMet()
        self.ssh.set_info(self.soft_info)
        self.ssh.cp_connect()

    def ssh_close(self):
        self.ssh.close()

    def go_conf(self):
        DeployConfCreate.ssh_echo_input(self.ssh, self.soft_info['conf_manage_ids'], self.soft_info['deploy_event_ids'])
        return True

    def copy_jar_package_in_host(self):
        des_file = os.path.join(self.soft_info['soft_install_url'], self.mvn_obj.project_package_name)
        des_file = des_file.replace("\\", "/")
        self.ssh.execcmd("mkdir -p %s" %self.soft_info['soft_install_url'])
        self.ssh.put_file(self.local_jar_package_path, des_file)
        return True

    def copy_jar_package_in_host_progress(self):
        if not int(self.ssh.percents) == 100:
            deploy_event_in(self.soft_info['deploy_event_ids'],
                            '上传文件：%s, 进度：%s%%' %(self.mvn_obj.project_package_name, self.ssh.percents), '2')
            time.sleep(2)
            self.copy_jar_package_in_host_progress()
        return True

    def judge_service_exist(self):
        """
        systemctl service判断方式
        """
        for conf_list_one in self.conf_list:
            if conf_list_one['conf_manage_code'] == 'service_file':
                self.service_file_data = conf_list_one

        conf_manage_path_list = os.path.split(self.service_file_data['conf_manage_path'])

        if len(conf_manage_path_list) == 2:
            self.service_file_name = conf_manage_path_list[1]
        else:
            deploy_event_in(self.soft_info['deploy_event_ids'],
                            '路径格式错误', '2')
            return False

        shell_command = 'systemctl status %s | grep Active | awk "{print $3}" | cut -d "(" -f2 | cut -d ")" -f1' %self.service_file_name

        command_result = self.ssh.execcmd(shell_command)

        if ReturnClass.if_ok(command_result):
            if not command_result['data'] or command_result['data'] == 'running':
                deploy_event_in(self.soft_info['deploy_event_ids'],
                                '服务已经存在，预备执行销毁动作', '2')
                return True

        deploy_event_in(self.soft_info['deploy_event_ids'],
                        '服务不存在，预备执行部署动作', '2')
        return False

    def service_stop(self):
        if self.soft_info.get('soft_stop_cmd'):
            deploy_event_in(self.soft_info['deploy_event_ids'],
                            '使用维护停止命令停止正在运行服务', '2')
            shell_command = self.soft_info['soft_stop_cmd']
        else:
            deploy_event_in(self.soft_info['deploy_event_ids'],
                            '使用服务文件名称解析服务名进行运行服务停止', '2')
            shell_command = 'systemctl stop %s' %self.service_file_name

        command_result = self.ssh.execcmd(shell_command)

        if ReturnClass.if_ok(command_result):
            deploy_event_in(self.soft_info['deploy_event_ids'],
                            '服务停止成功', '2')
        else:
            deploy_event_in(self.soft_info['deploy_event_ids'],
                            '服务停止失败：%s'%command_result["data"], '0')
            return False

        return True

    def git_pull(self):
        deploy_event_in(self.soft_info['deploy_event_ids'],
                        '开始拉取代码', '2')
        git_obj = GitClass()
        if os.path.exists(self.git_local_path):
            deploy_event_in(self.soft_info['deploy_event_ids'],
                            '已存在本地git目录，拉取最新代码', '2')
            gitexe_result = git_obj.pull(self.soft_info['branch'], self.git_local_path)
            if ReturnClass.if_ok(gitexe_result):
                deploy_event_in(self.soft_info['deploy_event_ids'],
                                '拉取最新代码成功', '2')
                return True
            else:
                deploy_event_in(self.soft_info['deploy_event_ids'],
                                '拉取最新代码失败: %s' % gitexe_result['data'], '0')
        else:
            deploy_event_in(self.soft_info['deploy_event_ids'],
                            '不存在本地git目录，创建新目录开始克隆', '2')
            os.makedirs(self.git_local_path)
            gitexe_result = git_obj.clone(self.soft_info['package_git_url'], self.soft_info['branch'], self.git_local_path)
            if ReturnClass.if_ok(gitexe_result):
                deploy_event_in(self.soft_info['deploy_event_ids'],
                                '克隆代码成功', '2')
                return True
            else:
                deploy_event_in(self.soft_info['deploy_event_ids'],
                                '克隆代码失败: %s' %gitexe_result['data'], '0')
        return False

    def mvn_packaging(self):
        deploy_event_in(self.soft_info['deploy_event_ids'],
                        '开始构建包，请稍后...', '2')
        mvnexe_result = self.mvn_obj.mvn_build(self.soft_info['maven_settings'], self.git_local_path, self.soft_info['deploy_package_versions'])
        if ReturnClass.if_ok(mvnexe_result):
            deploy_event_in(self.soft_info['deploy_event_ids'],
                            '构建包成功,已经推送至远程成库,开始拷贝包到本地仓库..', '2')

            self.local_jar_package_path = self.mvn_obj.copy_package_local_repository()

            if not self.local_jar_package_path:
                deploy_event_in(self.soft_info['deploy_event_ids'],
                                '拷贝包到本地仓库失败..', '0')
            return True
        else:
            deploy_event_in(self.soft_info['deploy_event_ids'],
                            '构建包失败：%s' %ReturnClass.get_value(mvnexe_result), '0')
        return False

    def check_status(self):
        if self.soft_info['soft_check_code'] and self.soft_info['soft_check_url']:
            check_count_ = 0
            while check_count > check_count_:
                check_count_ += 1

                deploy_event_in(self.soft_info['deploy_event_ids'],
                                '心跳检查中，第【%s】次' % check_count_, '2')

                check_status_result = self.ssh.check_status(self.soft_info['soft_check_code'],
                                                            self.soft_info['soft_check_url'])
                time.sleep(1)

                if ReturnClass.if_ok(check_status_result):
                    deploy_event_in(self.soft_info['deploy_event_ids'],
                                    '部署成功', '1')
                    return True

                time.sleep(check_period)

            deploy_event_in(self.soft_info['deploy_event_ids'],
                            '在120秒内，心跳检查失败。请检查配置，或者登录服务器查询服务状态', '0')
            return False
        else:
            deploy_event_in(self.soft_info['deploy_event_ids'],
                            '未设置心跳方式或者信息，默认部署完成', '1')

    def if_local_jar(self):
        self.local_package_path = self.mvn_obj.get_local_repository_package_path(self.soft_info['deploy_package_versions'],
                                                                       self.soft_info['package_name'])

        if self.local_package_path:
            self.local_jar_package_path = self.local_package_path
            deploy_event_in(self.soft_info['deploy_event_ids'],
                            '找到本地仓库包，预备使用本地包进行部署', '2')
            return True

        deploy_event_in(self.soft_info['deploy_event_ids'],
                        '未找到本地包', '2')
        return False

    def jar_mvn_download(self):
            if self.soft_info['deploy_package_versions'].find('SNAPSHOT') == -1:
                nexus_repository = "maven-releases"
            else:
                nexus_repository = "maven-snapshots"

            package_repository_info = sys_other_privilege_dict("package_repository")
            nexus_dict = {
                "nexus_url": package_repository_info['sys_other_privilege_url'],
                "nexus_user": package_repository_info['sys_other_privilege_user'],
                "nexus_pass": sql_decrypt(package_repository_info['sys_other_privilege_pass']),
                "nexus_repository": nexus_repository,
            }
            soft_dict = {
                "soft_groupid": self.soft_info['package_groupid'],
                "artifact": self.soft_info['package_name'],
                "soft_version": self.soft_info['deploy_package_versions'],
                "package_type_code": self.soft_info['package_type_code']
            }

            nexus_package_download_path = self.mvn_obj.get_nexus_package_download_path(nexus_dict, soft_dict)
            if nexus_package_download_path:
                if not self.mvn_obj.download_file(nexus_package_download_path, self.mvn_obj.package_local_repository_path):
                    return False
            else:
                return False

            self.local_jar_package_path = nexus_package_download_path

            return True

    def jar_start(self):
        command_result = self.ssh.execcmd(self.soft_info['soft_install_cmd'])
        if ReturnClass.if_ok(command_result):
            if not command_result['data'] or command_result['data'] != '0':
                command_result = self.ssh.execcmd(self.soft_info['soft_start_cmd'])
                if ReturnClass.if_ok(command_result):
                    if not command_result['data'] or command_result['data'] != '0':
                        return True
                else:
                    deploy_event_in(self.soft_info['deploy_event_ids'],
                                    '执行启动命令失败：%s' %ReturnClass.get_value(command_result), '0')

        return False

    def deploy_end(self):
        self.ssh.close()

    def exec_install_(self):
        deploy_event_in(self.soft_info['deploy_event_ids'],
                        '开始处理,请稍后', '2')

        self.git_local_path = os.path.join(settings.APP_CONF['TMPPATHGIT'], self.soft_info['package_name'])

        self.mvn_obj.analysis_pom_package_info(self.git_local_path)

        try:
            if not self.if_local_jar():
                if self.jar_mvn_download():
                    deploy_event_in(self.soft_info['deploy_event_ids'],
                                    '仓库包下载成功', '2')
                else:
                    deploy_event_in(self.soft_info['deploy_event_ids'],
                                    '仓库包下载失败，预备本地结构打包', '2')
                    if not self.git_pull():
                        return False

                    if not self.mvn_packaging():
                        return False

                    deploy_event_in(self.soft_info['deploy_event_ids'],
                                    '构建完成，拷贝包到本地仓库目录', '2')
                    self.mvn_obj.copy_package_local_repository()

            if self.judge_service_exist():
                if not self.service_stop():
                    return False

            if not self.go_conf():
                return False

            deploy_event_in(self.soft_info['deploy_event_ids'],
                            '上传包到服务器', '2')

            exec_copy_ = threading.Thread(target=self.copy_jar_package_in_host, args=())
            exec_copy_.start()

            self.copy_jar_package_in_host_progress()

            if not self.jar_start():
                return False

            self.check_status()

        except Exception as e:
            # deploy_event_in(self.soft_info['deploy_event_ids'],
            #                 '部署失败(%s)' %e, '0')
            deploy_event_in(self.soft_info['deploy_event_ids'],
                            '部署失败(%s)' % traceback.print_exc(), '0')
        return True